import { FileInfo } from './types';
import { CloudConfig, ConfigManager } from './ConfigManager';
import { Logger } from '../utils/Logger';

// 本地文件信息接口（用于上传）
interface LocalFileInfo {
  path: string;
  size: number;
  lastModified: Date;
  hash: string;
  relativePath: string;
}
import { TencentCloudService } from './cloud/TencentCloudService';
import { AliyunCloudService } from './cloud/AliyunCloudService';
import { BytedanceCloudService } from './cloud/BytedanceCloudService';
import { AWSCloudService } from './cloud/AWSCloudService';
import { HuaweiCloudService } from './cloud/HuaweiCloudService';

export interface UploadConfig {
  provider: string;
  localPath: string;
  remotePath: string;
  files: LocalFileInfo[];
}

export interface UploadProgress {
  currentFile: string;
  currentFileIndex: number;
  totalFiles: number;
  currentFileProgress: number;
  totalProgress: number;
  uploadedSize: number;
  totalSize: number;
  speed: number;
  remainingTime: number;
  status: 'uploading' | 'completed' | 'error' | 'cancelled' | 'retrying';
  error?: string;
  successCount: number;
  failedCount: number;
  retryCount: number;
  currentRetryAttempt: number;
}

export interface CloudServiceInterface {
  uploadFile(filePath: string, remotePath: string, onProgress?: (progress: number) => void): Promise<boolean>;
  listFiles(remotePath: string): Promise<FileInfo[]>;
  deleteFile(remotePath: string): Promise<boolean>;
}

// 失败文件信息接口
interface FailedFileInfo extends LocalFileInfo {
  retryCount: number;
  lastError: string;
}

export class CloudUploader {
  private configManager: ConfigManager;
  private isUploading: boolean = false;
  private shouldStop: boolean = false;
  private currentUploadService: CloudServiceInterface | null = null;
  private failedFiles: FailedFileInfo[] = [];
  private successCount: number = 0;
  private failedCount: number = 0;
  private readonly maxRetries: number = 3;

  constructor() {
    this.configManager = new ConfigManager();
  }

  /**
   * 开始上传
   */
  async startUpload(
    uploadConfig: UploadConfig,
    onProgress: (progress: UploadProgress) => void
  ): Promise<boolean> {
    if (this.isUploading) {
      throw new Error('上传正在进行中');
    }

    this.isUploading = true;
    this.shouldStop = false;
    this.failedFiles = [];
    this.successCount = 0;
    this.failedCount = 0;

    try {
      // 获取云服务配置
      const cloudConfig = await this.configManager.getConfig(uploadConfig.provider);
      if (!cloudConfig) {
        throw new Error(`未找到 ${uploadConfig.provider} 的配置`);
      }

      // 创建云服务实例
      this.currentUploadService = this.createCloudService(uploadConfig.provider, cloudConfig);

      // 计算总大小
      const totalSize = uploadConfig.files.reduce((sum, file) => sum + file.size, 0);
      let uploadedSize = 0;
      const startTime = Date.now();

      // 第一轮上传：逐个上传文件
      const uploadResult = await this.uploadFiles(
        uploadConfig.files,
        uploadConfig.remotePath,
        totalSize,
        uploadedSize,
        startTime,
        onProgress
      );

      if (!uploadResult.success) {
        return false;
      }

      uploadedSize = uploadResult.uploadedSize;

      // 重试失败的文件（最多3次）
      for (let retryAttempt = 1; retryAttempt <= this.maxRetries && this.failedFiles.length > 0; retryAttempt++) {
        if (this.shouldStop) {
          break;
        }

        Logger.info(`开始第 ${retryAttempt} 次重试，失败文件数: ${this.failedFiles.length}`);
        
        const retryFiles = [...this.failedFiles];
        this.failedFiles = [];

        const retryResult = await this.uploadFiles(
          retryFiles,
          uploadConfig.remotePath,
          totalSize,
          uploadedSize,
          startTime,
          onProgress,
          retryAttempt
        );

        if (!retryResult.success) {
          break;
        }

        uploadedSize = retryResult.uploadedSize;
      }

      // 最终统计
      const finalFailedCount = this.failedFiles.length;
      this.failedCount = finalFailedCount;

      onProgress({
        currentFile: '',
        currentFileIndex: uploadConfig.files.length,
        totalFiles: uploadConfig.files.length,
        currentFileProgress: 100,
        totalProgress: 100,
        uploadedSize: totalSize,
        totalSize,
        speed: 0,
        remainingTime: 0,
        status: finalFailedCount > 0 ? 'error' : 'completed',
        successCount: this.successCount,
        failedCount: finalFailedCount,
        retryCount: 0,
        currentRetryAttempt: 0,
        error: finalFailedCount > 0 ? `上传完成，成功: ${this.successCount}，失败: ${finalFailedCount}` : undefined
      });

      return finalFailedCount === 0;
    } catch (error) {
      Logger.error('上传失败:', error);
      onProgress({
        currentFile: '',
        currentFileIndex: 0,
        totalFiles: uploadConfig.files.length,
        currentFileProgress: 0,
        totalProgress: 0,
        uploadedSize: 0,
        totalSize: 0,
        speed: 0,
        remainingTime: 0,
        status: 'error',
        error: error instanceof Error ? error.message : '未知错误',
        successCount: this.successCount,
        failedCount: this.failedCount,
        retryCount: 0,
        currentRetryAttempt: 0
      });
      return false;
    } finally {
      this.isUploading = false;
      this.currentUploadService = null;
    }
  }

  /**
   * 上传文件列表
   */
  private async uploadFiles(
    files: LocalFileInfo[],
    remotePath: string,
    totalSize: number,
    initialUploadedSize: number,
    startTime: number,
    onProgress: (progress: UploadProgress) => void,
    retryAttempt: number = 0
  ): Promise<{ success: boolean; uploadedSize: number }> {
    let uploadedSize = initialUploadedSize;

    for (let i = 0; i < files.length; i++) {
      if (this.shouldStop) {
        onProgress({
          currentFile: '',
          currentFileIndex: i,
          totalFiles: files.length,
          currentFileProgress: 0,
          totalProgress: (uploadedSize / totalSize) * 100,
          uploadedSize,
          totalSize,
          speed: 0,
          remainingTime: 0,
          status: 'cancelled',
          successCount: this.successCount,
          failedCount: this.failedCount,
          retryCount: this.failedFiles.length,
          currentRetryAttempt: retryAttempt
        });
        return { success: false, uploadedSize };
      }

      const file = files[i];
      const fileRemotePath = `${remotePath}/${file.relativePath}`;

      try {
        let fileUploadedSize = 0;
        const fileStartTime = Date.now();

        await this.currentUploadService!.uploadFile(
          file.path,
          fileRemotePath,
          (fileProgress) => {
            fileUploadedSize = (fileProgress / 100) * file.size;
            const currentTotalUploaded = uploadedSize + fileUploadedSize;
            const elapsedTime = (Date.now() - startTime) / 1000;
            const speed = currentTotalUploaded / elapsedTime;
            const remainingSize = totalSize - currentTotalUploaded;
            const remainingTime = speed > 0 ? remainingSize / speed : 0;

            onProgress({
              currentFile: file.relativePath,
              currentFileIndex: i + 1,
              totalFiles: files.length,
              currentFileProgress: fileProgress,
              totalProgress: (currentTotalUploaded / totalSize) * 100,
              uploadedSize: currentTotalUploaded,
              totalSize,
              speed,
              remainingTime,
              status: 'uploading',
              successCount: this.successCount,
              failedCount: this.failedCount,
              retryCount: this.failedFiles.length,
              currentRetryAttempt: retryAttempt
            });
          }
        );

        uploadedSize += file.size;
        this.successCount++;
        Logger.info(`文件上传成功: ${file.relativePath}`);
      } catch (error) {
        Logger.error(`上传文件 ${file.relativePath} 失败:`, error);
        
        // 记录失败文件
        this.failedFiles.push({
          ...file,
          retryCount: 0,
          lastError: error instanceof Error ? error.message : '未知错误'
        });
        
        Logger.info(`文件上传失败，已记录到重试列表: ${file.relativePath}`);
      }
    }

    return { success: true, uploadedSize };
  }

  /**
   * 停止上传
   */
  async stopUpload(): Promise<boolean> {
    if (!this.isUploading) {
      return false;
    }

    this.shouldStop = true;
    return true;
  }

  /**
   * 创建云服务实例
   */
  private createCloudService(provider: string, config: CloudConfig): CloudServiceInterface {
    switch (provider) {
      case 'tencent':
        return new TencentCloudService(config);
      case 'aliyun':
        return new AliyunCloudService(config);
      case 'bytedance':
        return new BytedanceCloudService(config);
      case 'aws':
        return new AWSCloudService(config);
      case 'huawei':
        return new HuaweiCloudService(config);
      default:
        throw new Error(`不支持的云服务提供商: ${provider}`);
    }
  }

  /**
   * 测试云服务连接
   */
  async testConnection(config: CloudConfig): Promise<boolean> {
    try {
      // 创建云服务实例
      const cloudService = this.createCloudService(config.provider, config);
      
      // 尝试列出根目录文件来测试连接
      await cloudService.listFiles('/');
      
      return true;
    } catch (error) {
      Logger.error('测试连接失败:', error);
      throw error;
    }
  }

  /**
   * 获取上传状态
   */
  isUploadInProgress(): boolean {
    return this.isUploading;
  }
}